#!/bin/bash
# paths below must be absolute
tcdir="$PWD/tests"
tmpdir=/tmp/myarm-tmp
fail_file="$tmpdir/fail"
tracecmp="$PWD/tracecmp"
filter_trace="$PWD/filter_trace"
emulator="$PWD/armemu/armemu"
simexec="$tmpdir/a.out"
usage() {
	cat >&2 <<EOF
usage: run [-n|-c|-g] [-e [EMULATOR]] [-p] [-d TEST_CASE_DIR] TEST_CASE
	-n	do not filter simulation output
	-c	compare against reference trace
	-g	generate reference trace
	-e	run emulator instead of HDL simulation
	-p	run previously failed tests (implies -c)
	-d	specify directory where test cases are located
EOF
	exit 2
}
set -e
eval set -- `getopt -o ncge::pd: -- "$@"`
while true; do
	case "$1" in
		-n)
			mode=n
			shift
			;;
		-c)
			mode=c
			shift
			;;
		-g)
			mode=g
			shift
			;;
		-e)
			if [ "$2" != '' ]; then
				emulator="$2"
			fi
			run_emulator=1
			shift 2
			;;
		-p)
			mode=c
			run_prev_fail=1
			shift
			;;
		-d)
			tcdir="$2"
			if [[ "$tcdir" != /* ]]; then
				tcdir="$PWD/$tcdir"
			fi
			shift 2
			;;
		--)
			shift
			break
			;;
	esac
done
if [ "$run_prev_fail" != 1 ]; then
#	if [ ! -f "$fail_file" ]; then
#		echo >&2 "no such file: $fail_file"
#		exit 1
#	fi
#else
	[[ -z "$1" ]] && usage
fi
prompt() {
	case $1 in
		red)
			code=31
			;;
		green)
			code=32
			;;
		yellow)
			code=33
			;;
		*)
			code=37
			;;
	esac
	echo -e "\e[$code;1m==> $2\e[0m"
}
run() {
	make -C "$tcdir" "${@/%/.bin}"
	pushd "$tmpdir"
	for program; do
		cmd=("$simexec" +trace +memfile="$tcdir/$program.bin" +finish=10000 +dump="$tmpdir/$program.vcd")
		prompt yellow "Running $program..."
		if [ "$run_emulator" = 1 ]; then
			"$emulator" "$tcdir/$program.bin" | "$filter_trace" > trace
		fi
		if [ "$mode" = c ]; then
			"${cmd[@]}" | "$filter_trace" > trace
			if "$tracecmp" "$tcdir/$program.trace" trace; then
				prompt green "PASS $program"
			else
				prompt red "FAIL $program"
				fails=(${fails[@]} "$program")
			fi
		elif [ "$mode" = g ]; then
			"${cmd[@]}" | "$filter_trace" | tee "$tcdir/$program.trace"
		elif [ "$mode" = n ]; then
			"${cmd[@]}"
		else
			"${cmd[@]}" | "$filter_trace"
		fi
	done
	popd
}
mkdir -p $tmpdir
wd="$PWD"
if [ "$run_prev_fail" = 1 ]; then
	if [ -f "$fail_file" ]; then
		readarray -t case_list < "$fail_file"
	else
		readarray -t case_list < <(find "$tcdir" -name '*.s' | xargs basename -s .s)
	fi
	run "${case_list[@]}"
	printf "%s\n" "${fails[@]}" > "$fail_file"
else
	if [ "$1" = ALL ]; then
		readarray -t case_list < <(find "$tcdir" -name '*.s' | xargs basename -s .s)
		set "${case_list[@]}"
	fi
	run "$@"
fi
